﻿#include "guild_application_logic.h"

#include "GuildApplicationInfo_struct.h"
#include "GuildModuleApplication_struct.h"
#include "error/make_error_code.h"
#include "guild/guild_dump.hpp"
#include "guild/module/guild_module.h"
#include "guild/module/guild_module_loader.hpp"
#include "guild_brief_logic.h"
#include "guild_members_logic.h"
#include "guild_service_basic.h"

namespace guild_service {
bool GuildApplicationLogic::GetGuildModuleApplication(const guild_id_type guild_id,
                                        GuildModuleApplication& module_application) {
  return detail::GetGuildModule<GuildModuleApplication>(
      kGuildServiceBasicName, guild_id, kGuildModuleApplicationName,
      module_application);
}

bool GuildApplicationLogic::ApplyJoinGuild(
    const role_uuid_type role_uuid, const guild_id_type guild_id,
    const guildservicebasic_cpp::RoleSex role_sex, error_code& ec) {
  if (role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  GuildModuleApplication module_application;
  if (!GuildApplicationLogic::GetGuildModuleApplication(guild_id,
                                                        module_application)) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_LOAD_FAILED;
    return false;
  }

  constexpr std::size_t max_size = 10;
  std::size_t application_size = module_application.application_list.size();
  if (application_size >= max_size) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_FULL;
    return false;
  }
  {
    GuildApplicationInfo tmp_info;
    tmp_info.role_uuid = role_uuid;
    tmp_info.role_sex = role_sex;
    // tmp_info.apply_timestamp
    module_application.application_list.emplace_back(tmp_info);
  }

  if (!detail::SaveGuildModule<GuildModuleApplication>(
          kGuildServiceBasicName, module_application, guild_id, kGuildModuleApplicationName)) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_SAVE_FAILED;
    return false;
  }

  return true;
}

bool GuildApplicationLogic::ApproveJoinGuild(
    const role_uuid_type role_uuid, const role_uuid_type apply_role_uuid,
    error_code& ec) {
  if (role_uuid == kInvalidRoleUuid || apply_role_uuid == kInvalidRoleUuid) {
    ec = ErrorCode::ERR_INVALID_ROLE_UUID;
    return false;
  }

  std::vector<GuildMembersLogic::duty_type> duty_list{
      GuildMembersLogic::duty_type::GUILD_DUTY_CHAIRMAN,
      GuildMembersLogic::duty_type::GUILD_DUTY_VICE_CHAIRMAN};
  if (!GuildMembersLogic::CheckMemberDuty(role_uuid, duty_list)) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_NO_PERMISSION;
    return false;
  }

  const guild_id_type guild_id =
      GuildServiceBasicSingleton->GetGuildIdByRole(role_uuid);
  if (guild_id == kInvalidGuildId) {
    ec = ErrorCode::ERR_GUILD_NOT_EXIST;
    return false;
  }

  GuildModuleApplication module_application;
  if (!GuildApplicationLogic::GetGuildModuleApplication(guild_id,
                                                        module_application)) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_LOAD_FAILED;
    return false;
  }

  auto& app_list = module_application.application_list;
  {
    auto iter = std::find_if(
        app_list.begin(), app_list.end(),
        [apply_role_uuid](const GuildApplicationInfo& app_info) -> bool {
          return app_info.role_uuid == apply_role_uuid;
        });
    if (iter != app_list.end()) {
      if (!GuildMembersLogic::AddGuildMember(guild_id, apply_role_uuid, ec)) {
        return false;
      }
      app_list.erase(iter);
    } else {
      ec = ErrorCode::ERR_GUILD_MEMBERS_ROLE_NOT_EXIST;
      return false;
    }
  }

  if (!detail::SaveGuildModule<GuildModuleApplication>(kGuildServiceBasicName,
                                                 module_application, guild_id,
                                                 kGuildModuleApplicationName)) {
    ec = ErrorCode::ERR_GUILD_APPLICATION_SAVE_FAILED;
    return false;
  }

  return true;
}

}  // namespace guild_service